namespace SimpleWebServices.Web.UI.Html.Elements
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Xml;
    using System.Xml.Serialization;

    [XmlRoot("link")]
    public class Link : Element, IXmlSerializable
    {
        public Uri Hyperlink
        {
            get;
            set;
        }

        public string Relationship
        {
            get;
            set;
        }

        public string ReverseLink
        {
            get;
            set;
        }

        [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods", Justification = "The naming is intentionally the same as HTML.")]
        public string Type
        {
            get;
            set;
        }

        public static bool operator ==(Link obj, Link comparand)
        {
            bool result = false;

            if (object.ReferenceEquals(null, obj))
            {
                result = object.ReferenceEquals(null, comparand);
            }
            else
            {
                result = obj.Equals(comparand);
            }

            return result;
        }

        public static bool operator !=(Link obj, Link comparand)
        {
            bool result = false;

            if (object.ReferenceEquals(null, obj))
            {
                result = !object.ReferenceEquals(null, comparand);
            }
            else
            {
                result = !obj.Equals(comparand);
            }

            return result;
        }

        public override IElement Deserialize(string name, string type, string xml)
        {
            IElement result = null;

            if (null == type && "link".Equals(name, StringComparison.OrdinalIgnoreCase))
            {
                result = xml.Deserialize<Link>();
            }

            return result;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override bool Equals(object obj)
        {
            bool result = false;

            if (!object.ReferenceEquals(null, obj))
            {
                if (object.ReferenceEquals(this, obj))
                {
                    result = true;
                }
                else
                {
                    Link cast = obj as Link;

                    if (!object.ReferenceEquals(null, cast))
                    {
                        result = this.Hyperlink == cast.Hyperlink
                            && this.Relationship == cast.Relationship
                            && this.ReverseLink == cast.ReverseLink
                            && this.Type == cast.Type;
                    }
                }
            }

            return result;
        }

        public override void ReadXml(XmlReader reader)
        {
            string value = reader.GetAttribute("href");
            if (!string.IsNullOrEmpty(value))
            {
                this.Hyperlink = new Uri(value, UriKind.RelativeOrAbsolute);
            }

            value = reader.GetAttribute("rel");
            if (!string.IsNullOrEmpty(value))
            {
                this.Relationship = value;
            }

            value = reader.GetAttribute("rev");
            if (!string.IsNullOrEmpty(value))
            {
                this.ReverseLink = value;
            }

            value = reader.GetAttribute("type");
            if (!string.IsNullOrEmpty(value))
            {
                this.Type = value;
            }

            base.ReadXml(reader);
        }

        public override void WriteXml(XmlWriter writer)
        {
            if (null != this.Hyperlink)
            {
                writer.WriteAttributeString("href", this.Hyperlink.IsAbsoluteUri ? this.Hyperlink.AbsoluteUri : this.Hyperlink.OriginalString);
            }

            if (!string.IsNullOrEmpty(this.Relationship))
            {
                writer.WriteAttributeString("rel", this.Relationship);
            }

            if (!string.IsNullOrEmpty(this.ReverseLink))
            {
                writer.WriteAttributeString("rev", this.ReverseLink);
            }

            if (!string.IsNullOrEmpty(this.Type))
            {
                writer.WriteAttributeString("type", this.Type);
            }

            base.WriteXml(writer);
        }
    }
}